import TouchDot from "./TouchDot";
import { PieceType, PlayerType } from "./GameDefine";
import BasePiece from "./Pieces/BasePiece";

export default class Algorithm {

    //棋盘的二位数组,包含了所有棋子布局
    dotArray: Array<Array<TouchDot>> = [];
    playerType: PlayerType = PlayerType.PLT_RED;

    //检测棋子移动
    public checkPieceMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        if (!opDot || !tgDot || !opDot.piece) {
            return false;
        }
        //如果目标有自己的棋子不能移动
        if (tgDot.piece && tgDot.piece.playerType === opDot.piece.playerType) {
            return false;
        }

        switch (opDot.piece.pieceType) {
            case PieceType.PT_KING://将/帅
                return this.checkKingMove(opDot, tgDot);
            case PieceType.PT_MANDARIN://士/仕
                return this.checkMandarinMove(opDot, tgDot);
            case PieceType.PT_ELEPHANT://象/相
                return this.checkElephantMove(opDot, tgDot);
            case PieceType.PT_ROOKS://车
                return this.checkRooksMove(opDot, tgDot);
            case PieceType.PT_KNIGHTS://马
                return this.checkKnightsMove(opDot, tgDot);
            case PieceType.PT_CANNONS://炮
                return this.checkCannonsMove(opDot, tgDot);
            case PieceType.PT_PAWNS://兵
                return this.checkPawnsMove(opDot, tgDot);
            default:
                return false;
        }
    }

    //检测将军


    private checkKingMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let piece: BasePiece = opDot.piece;
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;
        let oColor: PlayerType = piece.playerType;

        //一次只能移动一格
        let mDir = oIndex.sub(tIndex);
        if (1 != (Math.abs(mDir.x) + Math.abs(mDir.y))) {
            return false;
        }

        //将的移动范围
        //y: 3-5
        if (tIndex.y < 3 || tIndex.y > 5) {
            return false;
        }
        if (oColor === this.playerType) {
            //我方只能在
            //x: 0-2
            if (tIndex.x < 0 || tIndex.x > 2) {
                return false;
            }
        }
        else {
            //对方只能在
            //x: 7-9
            if (tIndex.x < 7 || tIndex.x > 9) {
                return false;
            }
        }

        return true;
    }
    private checkMandarinMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let piece: BasePiece = opDot.piece;
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;
        let oColor: PlayerType = piece.playerType;

        //一次只能沿斜线移动一格
        let mDir = oIndex.sub(tIndex);
        if (1 != Math.abs(mDir.x) || 1 != Math.abs(mDir.y)) {
            return false;
        }

        //士的移动范围
        //y: 3-5
        if (tIndex.y < 3 || tIndex.y > 5) {
            return false;
        }
        if (oColor === this.playerType) {
            //我方只能在
            //x: 0-2
            if (tIndex.x < 0 || tIndex.x > 2) {
                return false;
            }
        }
        else {
            //对方只能在
            //x: 7-9
            if (tIndex.x < 7 || tIndex.x > 9) {
                return false;
            }
        }

        return true;
    }
    private checkElephantMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let piece: BasePiece = opDot.piece;
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;
        let oColor: PlayerType = piece.playerType;

        //象只能走田字
        let mDir = oIndex.sub(tIndex);
        if (2 != Math.abs(mDir.x) || 2 != Math.abs(mDir.y)) {
            return false;
        }

        //象不能过河
        if (oColor === this.playerType) {
            //我方只能在
            //x: 0-4
            if (tIndex.x > 4) {
                return false;
            }
        }
        else {
            //对方只能在
            //x: 5-9
            if (tIndex.x < 5) {
                return false;
            }
        }

        //田中间有棋子不能走
        let midIndex = cc.v2(mDir.x / 2, mDir.y / 2);
        midIndex = oIndex.sub(midIndex);
        if (midIndex.x < 0 || midIndex.y < 0 || this.dotArray[midIndex.x][midIndex.y].piece) {
            return false;
        }

        return true;
    }
    private checkRooksMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;

        //车只能走直线
        let mDir = oIndex.sub(tIndex);
        if (0 != mDir.x && 0 != mDir.y) {
            return false;
        }

        //路线上不能有棋子
        let lineIndex = mDir.clone();
        while (true) {
            lineIndex.x = lineIndex.x == 0 ? 0 : lineIndex.x > 0 ? --lineIndex.x : ++lineIndex.x;
            lineIndex.y = lineIndex.y == 0 ? 0 : lineIndex.y > 0 ? --lineIndex.y : ++lineIndex.y;
            if (0 == lineIndex.x && 0 == lineIndex.y) {
                break;
            }

            let newIndex = oIndex.sub(lineIndex);
            if (this.dotArray[newIndex.x][newIndex.y].piece) {
                return false;
            }
        }

        return true;
    }
    private checkKnightsMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;

        //马只能走日
        let mDir = oIndex.sub(tIndex);
        if (3 != (Math.abs(mDir.x) + Math.abs(mDir.y))
            || 2 != Math.abs(mDir.x) && 2 != Math.abs(mDir.y)) {
            return false;
        }

        //不能撇脚
        let newIndex = mDir.clone();
        newIndex.x /= 2;
        newIndex.y /= 2;
        if (Math.abs(newIndex.x) < 1) {
            newIndex.x = 0;
        }
        if (Math.abs(newIndex.y) < 1) {
            newIndex.y = 0;
        }
        newIndex = oIndex.sub(newIndex);

        if (this.dotArray[newIndex.x][newIndex.y].piece) {
            return false;
        }

        return true;
    }
    private checkCannonsMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;

        //炮只能走直线
        let mDir = oIndex.sub(tIndex);
        if (0 != mDir.x && 0 != mDir.y) {
            return false;
        }

        //统计路线上棋子数量
        let pieceCount: number = 0;
        let lineIndex = mDir.clone();
        while (true) {
            lineIndex.x = lineIndex.x == 0 ? 0 : lineIndex.x > 0 ? --lineIndex.x : ++lineIndex.x;
            lineIndex.y = lineIndex.y == 0 ? 0 : lineIndex.y > 0 ? --lineIndex.y : ++lineIndex.y;
            if (0 == lineIndex.x && 0 == lineIndex.y) {
                break;
            }

            let newIndex = oIndex.sub(lineIndex);
            if (this.dotArray[newIndex.x][newIndex.y].piece) {
                ++pieceCount;
            }
        }

        //如果目标点有敌方的棋子，那么必须中间要有一个棋子,反之中间不能有棋子
        return tgDot.piece ? (1 == pieceCount) : (0 == pieceCount);
    }
    private checkPawnsMove(opDot: TouchDot, tgDot: TouchDot): boolean {
        let piece: BasePiece = opDot.piece;
        let oIndex: cc.Vec2 = opDot.index;
        let tIndex: cc.Vec2 = tgDot.index;
        let oColor: PlayerType = piece.playerType;

        //兵一次只能走一格
        let mDir = oIndex.sub(tIndex);
        if (1 != (Math.abs(mDir.x) + Math.abs(mDir.y))) {
            return false;
        }

        //在各自地盘只能往前走
        if (oColor === this.playerType) {
            //自己方
            if (oIndex.x > tIndex.x) {
                return false;
            }
            //没过河之前不能横着走
            if (oIndex.x < 5 && mDir.y != 0) {
                return false;
            }
        }
        else {
            //对方
            if (oIndex.x < tIndex.x) {
                return false;
            }

            //没过河之前不能横着走
            if (oIndex.x > 4 && mDir.y != 0) {
                return false;
            }
        }

        return true;
    }
}
